package multiplex.dataaccess.dao;

import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import multiplex.dataaccess.DaoException;
import multiplex.model.BandeiraCartao;
import multiplex.model.PromocaoMeioPagamento;
import multiplex.model.SalaTipo;

public class PromocaoMeioPagamentoDao 
		extends AbstractDao implements IPromocaoDao<PromocaoMeioPagamento> {
	
	public PromocaoMeioPagamento get(int id) throws DaoException {
		try{
			PreparedStatement st = getConnection().prepareStatement("SELECT Promocao.id AS id, " +
					"Promocao.nome AS nome, Promocao.desconto AS desconto, Promocao.descricao AS descricao, " +
					"PromocaoMeioPagamento.intBandeiraCartao AS intBandeiraCartao, " +
					"PromocaoMeioPagamento.dataTermino AS dataTermino," +
					"PromocaoMeioPagamento.validaDuranteSemana AS validaDuranteSemana, " +
					"PromocaoMeioPagamento.validaDuranteFimDeSemana AS validaDuranteFimDeSemana FROM " +
					"PromocaoMeioPagamento, Promocao WHERE " +
					"PromocaoMeioPagamento.Promocao_id = Promocao.id AND " +
					"Promocao.id = ?");
			st.setInt(1, id);
			ResultSet rs = st.executeQuery();
			if(rs.next()){
				PromocaoMeioPagamento promocaoMeioPagamento = new PromocaoMeioPagamento();
				fillPromocaoMeioPagamento(promocaoMeioPagamento, rs);
				st.close();
				return promocaoMeioPagamento;
			}
		} catch(Exception e){
			throw new DaoException(e);
		}
		return null;
	}

	public List<PromocaoMeioPagamento> getAll() throws DaoException {
		List<PromocaoMeioPagamento> promocaoMeioPagamentoList = new ArrayList<PromocaoMeioPagamento>();
		try{
			PreparedStatement st = getConnection().prepareStatement("SELECT Promocao.id AS id, " +
					"Promocao.nome AS nome, Promocao.desconto AS desconto, Promocao.descricao AS descricao, " +
					"PromocaoMeioPagamento.intBandeiraCartao AS intBandeiraCartao, " +
					"PromocaoMeioPagamento.dataTermino AS dataTermino," +
					"PromocaoMeioPagamento.validaDuranteSemana AS validaDuranteSemana, " +
					"PromocaoMeioPagamento.validaDuranteFimDeSemana AS validaDuranteFimDeSemana FROM " +
					"PromocaoMeioPagamento, Promocao WHERE PromocaoMeioPagamento.Promocao_id = Promocao.id");
			ResultSet rs = st.executeQuery();
			while(rs.next()){
				PromocaoMeioPagamento promocaoMeioPagamento = new PromocaoMeioPagamento();
				fillPromocaoMeioPagamento(promocaoMeioPagamento, rs);
				promocaoMeioPagamentoList.add(promocaoMeioPagamento);
			}
			st.close();
			return promocaoMeioPagamentoList;
		}catch(Exception e){
			throw new DaoException(e);
		}
	}
	
		public void save(PromocaoMeioPagamento promocaoMeioPagamento) throws DaoException {
		try {
			try{
				getConnection().setAutoCommit(false);
				PreparedStatement stPromocao = getConnection().prepareStatement("INSERT INTO " +
						"Promocao(nome, descricao, desconto) VALUES (?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
				fillPreparatedStatementPromocao(stPromocao, promocaoMeioPagamento);
				stPromocao.execute();
				ResultSet rs = stPromocao.getGeneratedKeys();
				rs.next();
				promocaoMeioPagamento.setId(rs.getInt(1));
				PreparedStatement stPromocaoMeioPagamento = getConnection().prepareStatement(
						"INSERT INTO PromocaoMeioPagamento (Promocao_id, dataTermino, " +
						"validaDuranteSemana, validaDuranteFimDeSemana) " +
						"VALUES (?,?,?,?)");
				fillPreparatedStatementPromocaoMeioPagamento(stPromocaoMeioPagamento, promocaoMeioPagamento);
				stPromocaoMeioPagamento.execute();
				getConnection().commit();
				stPromocao.close();
				stPromocaoMeioPagamento.close();
			} catch(Throwable e){
				getConnection().rollback();
				throw new DaoException(e);
			} finally {
				getConnection().setAutoCommit(true);
			}
		} catch (Exception e) {
			throw new DaoException(e);
		}
	}
	
	public void update(PromocaoMeioPagamento promocaoMeioPagamento) throws DaoException {
		try {
			try{
				getConnection().setAutoCommit(false);
				PreparedStatement stPromocao = getConnection().prepareStatement("UPDATE Promocao " +
						"SET nome=?, descricao=?, desconto=? WHERE id=?");
				fillPreparatedStatementPromocao(stPromocao, promocaoMeioPagamento);
				stPromocao.setInt(4, promocaoMeioPagamento.getId());
				PreparedStatement stPromocaoMeioPagamento = getConnection().prepareStatement(
						"UPDATE PromocaoMeioPagamento SET dataTermino=?, " +
						"validaDuranteSemana=?, validaDuranteFimDeSemana=? " +
						"WHERE Promocao_id=?");
				fillPreparatedStatementPromocaoMeioPagamento(stPromocaoMeioPagamento, promocaoMeioPagamento);
				stPromocao.execute();
				stPromocaoMeioPagamento.execute();
				getConnection().commit();
				stPromocao.close();
				stPromocaoMeioPagamento.close();
			} catch(Throwable e){
				getConnection().rollback();
				throw new DaoException(e);
			} finally {
				getConnection().setAutoCommit(true);
			}
		} catch (Exception e) {
			throw new DaoException(e);
		}
	}

	public void remove(PromocaoMeioPagamento promocaoMeioPagamento) throws DaoException {
		// PromocaoMeioPagamento é apagada com base no CASCADE ALL
		try{
			PreparedStatement st = getConnection().prepareStatement(
					"DELETE FROM Promocao WHERE id=?");
			st.setInt(1, promocaoMeioPagamento.getId());
			st.execute();
			st.close();		
		}catch(Throwable e){
			throw new DaoException(e);
		}	
	}
	
	private void fillPromocaoMeioPagamento(PromocaoMeioPagamento promocaoMeioPagamento, ResultSet rs) throws SQLException {
		promocaoMeioPagamento.setId(rs.getInt("id"));
		promocaoMeioPagamento.setNome(rs.getString("nome"));
		promocaoMeioPagamento.setDescricao(rs.getString("descricao"));
		// recuperar bandeiraCartao
		int bandeiraTipoId = rs.getInt("intBandeiraCartao");
		BandeiraCartao[] tipos = BandeiraCartao.values();
		for (BandeiraCartao tipo : tipos) {
			if (tipo.getId()==bandeiraTipoId) {
				promocaoMeioPagamento.setBandeiraCartao(tipo);
				break;
			}
		}
		promocaoMeioPagamento.setDesconto(rs.getFloat("desconto"));
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(rs.getDate("dataTermino"));
		promocaoMeioPagamento.setDataTermino(calendar);
		promocaoMeioPagamento.setValidaDuranteSemana(rs.getBoolean("validaDuranteSemana"));
		promocaoMeioPagamento.setValidaDuranteFimDeSemana(rs.getBoolean("validaDuranteFimDeSemana"));
	}
	
	private void fillPreparatedStatementPromocao(PreparedStatement st, PromocaoMeioPagamento promocaoMeioPagamento) 
			throws SQLException {
		st.setString(1,promocaoMeioPagamento.getNome());
		st.setString(2, promocaoMeioPagamento.getDescricao());
		st.setDouble(3,promocaoMeioPagamento.getDesconto());
	}
	
	private void fillPreparatedStatementPromocaoMeioPagamento(PreparedStatement st, PromocaoMeioPagamento promocaoMeioPagamento) 
			throws SQLException {
		st.setInt(1,promocaoMeioPagamento.getId());
		st.setDate(2, new Date(promocaoMeioPagamento.getDataTermino().getTimeInMillis()));
		st.setBoolean(3, promocaoMeioPagamento.isValidaDuranteSemana());
		st.setBoolean(4, promocaoMeioPagamento.isValidaDuranteFimDeSemana());
	}
	
}
